package com.atguigu.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.cmn.controller.DictReadListener;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 * 组织架构表 服务实现类
 * </p>
 *
 * @author xueyoupeng
 * @since 2023-06-06
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Autowired
    DictReadListener dictReadListener;
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    @Cacheable(value = "dict_cache_findChildData",key = "'dict_' + #id")
    public List<Dict> findChildData(Long id) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",id);//列名

        List<Dict> dictList = baseMapper.selectList(queryWrapper);

        //判断集合中的每个数字字典是否有下级
        dictList.forEach(dict -> {
            boolean bool = this.hasChildren(dict);
            dict.setHasChildren(bool);
        });
        return dictList;
    }

    @Override
    @CacheEvict(value = "dict_cache_findChildData", allEntries = true,beforeInvocation = true)
    public void importData(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            EasyExcel.read(inputStream, DictEeVo.class, dictReadListener)
                    .sheet()// 读取默认第一个sheet表
                    .doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            //1、设置响应头(文件下载时使用) 如果文件名是中文，需要编码
            String filename = "数据字典列表";
            //Content-disposition 用来设置下载的文件的文件名称
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition","attachment;filename=" + URLEncoder.encode(filename, "utf-8") + ".xlsx");
            //Content-Type 指定响应的内容类型  application/json  application/text/html application/vnd.ms-excel  application/pdf
            response.setContentType("application/vnd.ms-excel");//设置响应内容类型（也是一个响应头）

            //2、查询所有的数据字典，记性泛型转换
            String jsonString = JSON.toJSONString(this.list());
            List<DictEeVo> list = JSON.parseArray(jsonString, DictEeVo.class);

            //3、获取文件下载所需要的响应输出流
            ServletOutputStream outputStream = response.getOutputStream();

            //4、excel的api
            EasyExcel.write(outputStream, DictEeVo.class)
                    .sheet()
                    .doWrite(list);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void exportDataByIds(List<Long> ids, HttpServletResponse response) {

        try {
            //1.设置响应头
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.ms-excel");
            String filename = "数据字典列表.xlsx";
            response.addHeader("Content-disposition","attachment;filename=" + URLEncoder.encode(filename,"utf-8"));

            //2、响应输出流程
            ServletOutputStream outputStream = response.getOutputStream();

            //3、使用响应输出流创建ExcelWriter（该对象实现写入多个sheet表）
            ExcelWriter excelWriter = EasyExcel.write(outputStream, DictEeVo.class).build();

            //id：选中的一级数据字典的主键
            for (Long id: ids) {
                //4、数据集
                String jsonString = JSONObject.toJSONString(this.findChildData(id));
                List<DictEeVo> list = JSONObject.parseArray(jsonString, DictEeVo.class);

                //5、sheet对象 ，sheet表名称显示该一级数据字典的名称name
                String name = baseMapper.selectById(id).getName();
                WriteSheet sheet = EasyExcel.writerSheet(name).build();

                excelWriter.write(list,sheet);
            }

            //6.完成
            excelWriter.finish();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //省市区 or  医院等级
    @Override
    public String getName(String value, String dictCode) {
        if (StringUtils.isEmpty(dictCode)){
            //根据value查询name = 省市区名称
            QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("value",value);

            //如果该条件对应的记录行数超过1，会报错
            Dict dict = baseMapper.selectOne(queryWrapper);

            return dict.getName();
        }else {
            //根据value和dictCode查询 = 医院等级
            QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("VALUE",value);
            queryWrapper.eq("parent_id",this.findByDictCode(dictCode).getId());

            Dict dict = baseMapper.selectOne(queryWrapper);

            return dict.getName();
        }
    }

    @Override
    public List<Dict> findListByDictCode(String dictCode) {
        //要求：前端不传递86，传递dict_code(Province)
        //SELECT * FROM dict WHERE parent_id = (SELECT id FROM dict WHERE dict_code = 'Province')
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",this.findByDictCode(dictCode).getId());

        List<Dict> dictList = baseMapper.selectList(queryWrapper);
        return dictList;
    }

    private Dict findByDictCode(String dictCode) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dict_code",dictCode);
        return baseMapper.selectOne(queryWrapper);
    }


    //判断dict是否存在下级
    private boolean hasChildren(Dict dict) {
        Long id = dict.getId();

        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",id);

        Integer num = baseMapper.selectCount(queryWrapper);

        return num > 0;
    }

    //缓存： my_dict_id---dict   数字典的主键 + 数据字典对象
    //根据id更新某一个数据字典
    //每次方法体都会执行，并且每次都会添加一组k-v
    //更新缓存
    //特点：每次方法体都会执行，并且每次都会生成一组k-v
    @CachePut(value = "my_cache",key = "'my_dict_'+#dict.id")
    public Dict updateByDictId(Dict dict){
        baseMapper.updateById(dict);
        return dict;
    }
}
